from typing import List, Optional, Dict, Any
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, and_, or_, func

from app.models.user import Dept, User
from app.services.base import BaseService


class DeptService(BaseService[Dept]):
    """部门服务"""

    def __init__(self):
        super().__init__(Dept)

    async def get_dept_tree(
        self, db: AsyncSession, *, tenant_id: str, include_user_count: bool = False
    ) -> List[dict]:
        """获取部门树形结构"""
        query = select(Dept).where(
            and_(
                Dept.tenant_id == tenant_id,
                Dept.del_flag == '0'
            )
        ).order_by(Dept.order_num.asc())

        result = await db.execute(query)
        depts = result.scalars().all()

        # 构建树形结构
        dept_dict = {}
        for dept in depts:
            # 获取用户数量（如果需要）
            user_count = 0
            if include_user_count:
                user_count_query = select(func.count(User.id)).where(
                    and_(
                        User.dept_id == dept.id,
                        User.tenant_id == tenant_id,
                        User.del_flag == '0'
                    )
                )
                user_count_result = await db.execute(user_count_query)
                user_count = user_count_result.scalar() or 0

            dept_dict[dept.id] = {
                "id": dept.id,
                "name": dept.name,
                "parent_id": dept.parent_id,
                "ancestors": dept.ancestors,
                "order_num": dept.order_num,
                "leader": dept.leader,
                "phone": dept.phone,
                "email": dept.email,
                "status": dept.status,
                "user_count": user_count,
                "created_at": dept.created_at.isoformat() if dept.created_at else None,
                "updated_at": dept.updated_at.isoformat() if dept.updated_at else None,
                "children": []
            }

        # 构建父子关系
        root_depts = []
        for dept_id, dept in dept_dict.items():
            if dept["parent_id"] == 0:
                root_depts.append(dept)
            else:
                parent = dept_dict.get(dept["parent_id"])
                if parent:
                    parent["children"].append(dept)

        return root_depts

    async def get_dept_list(
        self, db: AsyncSession, *, tenant_id: str, status_filter: Optional[bool] = None
    ) -> List[dict]:
        """获取部门列表（扁平结构）"""
        query = select(Dept).where(
            and_(
                Dept.tenant_id == tenant_id,
                Dept.del_flag == '0'
            )
        )

        if status_filter is not None:
            query = query.where(Dept.status == status_filter)

        query = query.order_by(Dept.order_num.asc())

        result = await db.execute(query)
        depts = result.scalars().all()

        return [
            {
                "id": dept.id,
                "name": dept.name,
                "parent_id": dept.parent_id,
                "leader": dept.leader,
                "phone": dept.phone,
                "email": dept.email,
                "status": dept.status
            }
            for dept in depts
        ]

    async def create_dept(
        self, db: AsyncSession, *, obj_in: Dict[str, Any], tenant_id: str
    ) -> Dept:
        """创建部门"""
        # 处理祖级列表
        if obj_in.get("parent_id", 0) > 0:
            parent_dept = await self.get(db, id=obj_in["parent_id"])
            if parent_dept and parent_dept.tenant_id == tenant_id:
                ancestors = parent_dept.ancestors + f",{parent_dept.id}" if parent_dept.ancestors else str(parent_dept.id)
                obj_in["ancestors"] = ancestors
            else:
                raise ValueError("父部门不存在")
        else:
            obj_in["ancestors"] = ""

        # 创建部门
        return await self.create(db, obj_in=obj_in, tenant_id=tenant_id)

    async def update_dept(
        self, db: AsyncSession, *, db_obj: Dept, obj_in: Dict[str, Any]
    ) -> Dept:
        """更新部门"""
        # 如果父部门发生变化，需要更新祖级列表
        if "parent_id" in obj_in and obj_in["parent_id"] != db_obj.parent_id:
            if obj_in["parent_id"] == db_obj.id:
                raise ValueError("不能将自己设置为父部门")

            # 检查是否设置为自己的子部门
            if obj_in["parent_id"] > 0:
                current_ancestors = db_obj.ancestors.split(",") if db_obj.ancestors else []
                if str(obj_in["parent_id"]) in current_ancestors:
                    raise ValueError("不能将子部门设置为父部门")

                # 获取新的父部门
                parent_dept = await self.get(db, id=obj_in["parent_id"])
                if parent_dept and parent_dept.tenant_id == db_obj.tenant_id:
                    ancestors = parent_dept.ancestors + f",{parent_dept.id}" if parent_dept.ancestors else str(parent_dept.id)
                    obj_in["ancestors"] = ancestors
                else:
                    raise ValueError("父部门不存在")
            else:
                obj_in["ancestors"] = ""

        return await self.update(db, db_obj=db_obj, obj_in=obj_in)

    async def delete_dept(
        self, db: AsyncSession, *, dept_id: int, tenant_id: str
    ) -> bool:
        """删除部门"""
        dept = await self.get(db, id=dept_id)
        if not dept or dept.tenant_id != tenant_id:
            return False

        # 检查是否有子部门
        children_query = select(Dept.id).where(
            and_(
                Dept.parent_id == dept_id,
                Dept.tenant_id == tenant_id,
                Dept.del_flag == '0'
            )
        )
        children_result = await db.execute(children_query)
        if children_result.scalar():
            raise ValueError("存在子部门，无法删除")

        # 检查是否有用户
        user_count_query = select(func.count(User.id)).where(
            and_(
                User.dept_id == dept_id,
                User.tenant_id == tenant_id,
                User.del_flag == '0'
            )
        )
        user_count_result = await db.execute(user_count_query)
        user_count = user_count_result.scalar() or 0
        if user_count > 0:
            raise ValueError(f"该部门下有 {user_count} 个用户，无法删除")

        # 软删除
        return await self.delete(db, id=dept_id)

    async def get_dept_users(
        self, db: AsyncSession, *, dept_id: int, tenant_id: str
    ) -> List[dict]:
        """获取部门下的用户列表"""
        query = select(User).where(
            and_(
                User.dept_id == dept_id,
                User.tenant_id == tenant_id,
                User.del_flag == '0'
            )
        ).order_by(User.created_at.desc())

        result = await db.execute(query)
        users = result.scalars().all()

        return [
            {
                "id": user.id,
                "username": user.username,
                "nickname": user.nickname,
                "email": user.email,
                "phone": user.phone,
                "status": user.status,
                "created_at": user.created_at.isoformat() if user.created_at else None
            }
            for user in users
        ]

    async def search_depts(
        self, db: AsyncSession, *, tenant_id: str, keyword: str
    ) -> List[dict]:
        """搜索部门"""
        query = select(Dept).where(
            and_(
                Dept.tenant_id == tenant_id,
                Dept.del_flag == '0',
                or_(
                    Dept.name.like(f"%{keyword}%"),
                    Dept.leader.like(f"%{keyword}%"),
                    Dept.phone.like(f"%{keyword}%"),
                    Dept.email.like(f"%{keyword}%")
                )
            )
        ).order_by(Dept.order_num.asc())

        result = await db.execute(query)
        depts = result.scalars().all()

        return [
            {
                "id": dept.id,
                "name": dept.name,
                "parent_id": dept.parent_id,
                "ancestors": dept.ancestors,
                "order_num": dept.order_num,
                "leader": dept.leader,
                "phone": dept.phone,
                "email": dept.email,
                "status": dept.status,
                "created_at": dept.created_at.isoformat() if dept.created_at else None,
                "updated_at": dept.updated_at.isoformat() if dept.updated_at else None
            }
            for dept in depts
        ]


# 创建部门服务实例
dept_service = DeptService()